home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 11 - 1995 / 11.04 Apr 95 / TreeAppƒ / Eric's C++ Libraries / Interface Classes / CPPText.cp < prev    next >
Encoding:
Text File  |  1996-04-04  |  30.4 KB  |  1,193 lines  |  [TEXT/KAHL]

  1. /********************************************************* DEFINITION
  2.     DATE:    9/19/93
  3.     AUTHOR: Eric R. Rosé
  4.     
  5.     CLASS:  CPPText
  6.     
  7.     SUPERCLASS: CPPObject
  8.     
  9.         This C++ class manages a textedit area, and a horizontal and
  10.         vertical scrollbar which let you adjust the text.
  11.     
  12. ********************************************************************/
  13.  
  14. #include <stdlib.h>
  15. #include <CPPText.h>
  16. #include <CPPWindow.h>
  17. #include <ctype.h>
  18. #include <Commands.h>
  19. #include <mathTools.h>
  20.  
  21. extern Rect kEmptyRect;
  22.  
  23. /*-----------------------------------------------------------------*/
  24. /*---------------------- CALLBACK VARIABLES -----------------------*/
  25. /*-----------------------------------------------------------------*/
  26.  
  27.     // Initialize the class member variables used in the callbacks
  28.     CPPText *CPPText::gCurrentTE = NULL;
  29.     ControlHandle CPPText::gVScroll = NULL;
  30.     ControlHandle CPPText::gHScroll = NULL;
  31.     TEHandle CPPText::gTextBlock = NULL;
  32.  
  33. /*-----------------------------------------------------------------*/
  34. /*------------------------ PUBLIC METHODS -------------------------*/
  35. /*-----------------------------------------------------------------*/
  36.  
  37.     CPPText::CPPText (CPPWindow *OurWindow,
  38.                               Rect *ViewArea,
  39.                               Rect *DestArea,
  40.                               short    MaxLength,
  41.                               Boolean UseHScroll,
  42.                               Boolean UseVScroll,
  43.                               short Font, short FSize) :
  44.                 CPPVisualObject (OurWindow, ViewArea, TRUE)
  45.     {
  46.         MakeTEArea (OurWindow, ViewArea, DestArea, MaxLength, 
  47.                     UseHScroll, UseVScroll, Font, FSize);
  48.     }
  49.  
  50. /*-----------------------------------------------------------------*/
  51.  
  52.     CPPText::CPPText (CPPWindow *OurWindow,
  53.                               short    MaxLength,
  54.                               Boolean UseHScroll,
  55.                               Boolean UseVScroll,
  56.                               short Font, short FSize) :
  57.                 CPPVisualObject (OurWindow,
  58.                                  &((OurWindow->GetWindow())->portRect), 
  59.                                    TRUE)
  60.     {
  61.         Rect    ViewRect;
  62.         Rect    DestRect;
  63.         
  64.         if (OurWindow)
  65.           {
  66.               ViewRect = (OurWindow->GetWindow())->portRect;
  67.               SetRect (&DestRect, 0, 0, kPageWidth, kPageHeight);
  68.               MakeTEArea(OurWindow, &ViewRect, &DestRect, MaxLength,
  69.                           UseHScroll, UseVScroll, Font, FSize);
  70.           }
  71.     }
  72.     
  73. /*-----------------------------------------------------------------*/
  74.     
  75.     CPPText::~CPPText (void)
  76.     /* Dispose of the controls and TEHandle used by the object */
  77.     {
  78.         if (this->TextBlock)
  79.           TEDispose(this->TextBlock);
  80.         if (this->HScroll)
  81.           DisposeControl(this->HScroll);
  82.         if (this->VScroll)
  83.           DisposeControl(this->VScroll);
  84.     }
  85.  
  86. /*-----------------------------------------------------------------*/
  87.  
  88.     Boolean    CPPText::Member (char *className)
  89.     {
  90.         if (strcmp(className, CPPText::ClassName()) == 0)
  91.           return TRUE;
  92.         else
  93.           return CPPVisualObject::Member(className);
  94.     }
  95.     
  96. /*-----------------------------------------------------------------*/
  97.  
  98.     char    *CPPText::ClassName (void)
  99.     {
  100.         return "CPPText";
  101.     }
  102.  
  103. /*-----------------------------------------------------------------*/
  104.  
  105.     Boolean    CPPText::DoCommand (short commandID)
  106.     /* do a command associated with a menu */
  107.     {
  108.         switch (commandID) {
  109.             case kCmdCut :
  110.                 DoCut();
  111.                 break;
  112.             case kCmdCopy :    
  113.                 DoCopy();
  114.                 break;
  115.             case kCmdPaste :
  116.                 DoPaste();
  117.                 break;
  118.             case kCmdSelectAll :
  119.                 DoSelectAll();
  120.                 break;
  121.             case kCmdClear :
  122.                 if (this->TextBlock)
  123.                   TEDelete(this->TextBlock);
  124.                 break;
  125.             default:
  126.                 return CPPVisualObject::DoCommand(commandID);
  127.                 break;
  128.         }
  129.         
  130.         return TRUE;
  131.     }
  132.  
  133. /*-----------------------------------------------------------------*/
  134.  
  135.     void CPPText::SetMinSize (short mwidth, short mheight)
  136.     {
  137.         this->TEminWidth = mwidth;
  138.         this->TEminHeight = mheight;
  139.     }
  140.  
  141. /*-----------------------------------------------------------------*/
  142.  
  143.     void CPPText::SetMaxSize (short mwidth, short mheight)
  144.     {
  145.         this->TEmaxWidth = mwidth;
  146.         this->TEmaxHeight = mheight;
  147.     }
  148.  
  149. /*-----------------------------------------------------------------*/
  150.  
  151.     void CPPText::Activate (Boolean nowActive)
  152.     /* activate or deactivate the text depending on DoActivate */
  153.     /* Is Override */
  154.     {
  155.         short    HiliteValue = (nowActive) ? 0 : 255;
  156.         
  157.         CPPVisualObject::Activate(nowActive);
  158.         
  159.         if (this->TextBlock)
  160.           {
  161.             if (nowActive)
  162.               TEActivate(this->TextBlock);
  163.             else
  164.               TEDeactivate (this->TextBlock);
  165.             AdjustScrollBar();
  166.             
  167.             if (this->VScroll)
  168.               HiliteControl (this->VScroll, HiliteValue);
  169.             if (this->HScroll)
  170.               HiliteControl (this->HScroll, HiliteValue);
  171.           }
  172.     }
  173.  
  174. /*-----------------------------------------------------------------*/
  175.  
  176.     void CPPText::DoIdle (void)
  177.     /* Is Override */
  178.     {
  179.         if (this->IsActive() && this->TextBlock)
  180.           TEIdle(this->TextBlock);
  181.     }
  182.  
  183. /*-----------------------------------------------------------------*/
  184.  
  185.     void CPPText::TypeChar (unsigned char TheKey)
  186.     /* type a character into the TE area at the current insertion point */
  187.     {
  188.         Boolean    canType = TRUE;
  189.         short    SelectionLen = 0;
  190.         
  191.         if (this->TextBlock)
  192.           {
  193.               SelectionLen = (*this->TextBlock)->selEnd - 
  194.                              (*this->TextBlock)->selStart; 
  195.               if (isprint(TheKey))
  196.                 canType = (*this->TextBlock)->teLength - SelectionLen < 
  197.                                 this->maxTextLen;
  198.             if (canType)
  199.               {
  200.                 TEKey(TheKey, this->TextBlock);
  201.                 AdjustScrollBar();    
  202.                 CheckInsertion();
  203.               }
  204.           }
  205.     }
  206.  
  207. /*-----------------------------------------------------------------*/
  208.  
  209.     void CPPText::DoCut (void)
  210.     /* cut the current selection of the TE area */
  211.     {
  212.         long    dummy;
  213.         
  214.         if (this->TextBlock)
  215.           {
  216.             CheckInsertion();
  217.             TECut (this->TextBlock);
  218.             AdjustScrollBar();
  219.             CheckInsertion();
  220.             dummy = ZeroScrap();
  221.             dummy = TEToScrap();
  222.           }
  223.     }
  224.  
  225. /*-----------------------------------------------------------------*/
  226.  
  227.     void CPPText::DoCopy (void)
  228.     /* copy the current selection of the TE area */
  229.     {
  230.         long    dummy;
  231.     
  232.         if (this->TextBlock)
  233.           {
  234.             AdjustScrollBar();
  235.             TECopy (this->TextBlock);
  236.             dummy = ZeroScrap();
  237.             dummy = TEToScrap();
  238.           }
  239.     }
  240.  
  241. /*-----------------------------------------------------------------*/
  242.  
  243.     void CPPText::DoPaste (void)
  244.     /* paste the contents of the scrap into the TE area */
  245.     {
  246.         long    dummy;
  247.         short    SelectionLen;
  248.     
  249.         if (this->TextBlock)
  250.           {
  251.               SelectionLen = (*this->TextBlock)->selEnd - 
  252.                              (*this->TextBlock)->selStart; 
  253.               if (TEFromScrap() != noErr)
  254.                 SysBeep(5);
  255.               else
  256.                 {
  257.                 CheckInsertion();
  258.                 if ((TEGetScrapLen() + 
  259.                     (*this->TextBlock)->teLength -
  260.                     SelectionLen) <= this->maxTextLen)
  261.                   {    // if the selection will fit, paste it in
  262.                     TEPaste (this->TextBlock);
  263.                     AdjustScrollBar();
  264.                     CheckInsertion();
  265.                   }
  266.                 else    // change the scrap size and paste
  267.                   {
  268.                       TESetScrapLen(this->maxTextLen - 
  269.                                     (*this->TextBlock)->teLength + 
  270.                                     SelectionLen);
  271.                     TEPaste (this->TextBlock);
  272.                     AdjustScrollBar();
  273.                     CheckInsertion();
  274.                   }
  275.                 }
  276.           }
  277.     }
  278.  
  279. /*-----------------------------------------------------------------*/
  280.  
  281.     void CPPText::DoClear (void)
  282.     /* Clear the current selection in the TE area */
  283.     {
  284.         long    dummy;
  285.     
  286.         if (this->TextBlock)
  287.           {
  288.             CheckInsertion();
  289.             TEDelete (this->TextBlock);
  290.             AdjustScrollBar();
  291.             CheckInsertion();
  292.           }
  293.     }
  294.  
  295. /*-----------------------------------------------------------------*/
  296.  
  297.     void CPPText::DoSelectAll (void)
  298.     /* select all of the text in the TE area */
  299.     {
  300.         if (this->TextBlock)
  301.           {
  302.             CheckInsertion();
  303.             TESetSelect(0, 32000, this->TextBlock);
  304.             AdjustScrollBar();
  305.             CheckInsertion();
  306.           }
  307.     }
  308.  
  309. /*-----------------------------------------------------------------*/
  310.  
  311.     short    CPPText::GetTextLen (void)
  312.     {
  313.         if (this->TextBlock)
  314.           return (**this->TextBlock).teLength;
  315.         else
  316.           return 0;
  317.     }
  318.  
  319. /*-----------------------------------------------------------------*/
  320.  
  321.     CharsHandle    CPPText::GetTheText (void)
  322.     /* return a handle to the text in the TE object */
  323.     {
  324.         if (this->TextBlock)
  325.           return TEGetText (this->TextBlock);
  326.         else
  327.           return NULL;
  328.     }
  329.  
  330. /*-----------------------------------------------------------------*/
  331.     
  332.     Boolean    CPPText::DoKey (char theKey, short modifiers, short what)
  333.     {
  334.         if (!IsVisible()) return FALSE;
  335.         
  336.         if (modifiers & cmdKey) 
  337.           {        /* Command key down. */
  338.             if (what == keyDown) 
  339.               {    // handle default edit commands
  340.                 switch (theKey) {
  341.                     case 'x' :
  342.                     case 'X' : DoCut(); break;
  343.                     case 'c' :
  344.                     case 'C' : DoCopy(); break;
  345.                     case 'v' :
  346.                     case 'V' : DoPaste(); break;
  347.                     case 'a' :
  348.                     case 'A' : DoSelectAll(); break;
  349.                     default  : return FALSE;    // unknown command
  350.                         break;
  351.                 }
  352.                 return TRUE;    // we handled the cut/copy/paste
  353.                 }
  354.           }
  355.         else
  356.           TypeChar (theKey);
  357.     }
  358.  
  359. /*-----------------------------------------------------------------*/
  360.  
  361.     Boolean CPPText::DoClick (EventRecord *theEvent)
  362.     /* Is Override */
  363.     {
  364.         WindowPtr    theWindow;
  365.         short        code, part;
  366.         ControlHandle    hitControl;
  367.         Point        myPt = theEvent->where;
  368.         TEPtr        TE;
  369.         Boolean        shiftDown = (theEvent->modifiers & shiftKey) ? TRUE : FALSE;
  370.         
  371.         if (!IsVisible()) return FALSE;
  372.         
  373.           code = FindWindow(theEvent->where, &theWindow);
  374.           if (theWindow == this->owningWindow)
  375.             {
  376.               Global2Local (&myPt);
  377.             part = FindControl(myPt, theWindow, &hitControl);
  378.             
  379.             // now respond to the click
  380.             if (hitControl)        // if they clicked in a scrollbar
  381.               {
  382.                 if (hitControl == this->HScroll)
  383.                   DoHScroller (myPt, part);
  384.                 else
  385.                 if (hitControl ==  this->VScroll)
  386.                   DoVScroller (myPt, part);
  387.                 else
  388.                   return FALSE;
  389.               }
  390.             else                // if they clicked in the TE area
  391.               {
  392.                   if (this->TextBlock)
  393.                     {
  394.                         TE = *this->TextBlock;
  395.                         if (PtInRect(myPt, &TE->viewRect))
  396.                           {
  397.                               gVScroll = this->VScroll;
  398.                               gHScroll = this->HScroll;
  399.                               gTextBlock = this->TextBlock;
  400.                               gCurrentTE = this;
  401.                             TEClick (myPt, shiftDown, this->TextBlock);
  402.                           }
  403.                         else
  404.                           return FALSE;
  405.                     }
  406.                   else
  407.                     return FALSE;
  408.               }    
  409.             }
  410.     }
  411.  
  412. /*-----------------------------------------------------------------*/
  413.  
  414.     void CPPText::InsertTextPtr (Ptr theText, long textLen, 
  415.                                     long insertWhere, 
  416.                                     Boolean ScrollToInsertion)
  417.     /* insert the text pointed to by TheText into the TE area */
  418.     /* at the specified location */
  419.     {
  420.         short    maxAllowed;        // use to keep within length limits
  421.         
  422.         if (this->TextBlock && theText)
  423.           {
  424.               maxAllowed = this->maxTextLen - (*this->TextBlock)->teLength;
  425.               
  426.               // let us watch what's going on
  427.             if (ScrollToInsertion)
  428.               CheckInsertion();
  429.             
  430.             // set the selection and insert
  431.             TESetSelect(insertWhere, insertWhere, this->TextBlock);
  432.             TEInsert(theText, Min(maxAllowed, textLen), this->TextBlock);
  433.             
  434.             // adjust for the text we inserted
  435.             if (ScrollToInsertion)
  436.               CheckInsertion();
  437.           }
  438.     }
  439.  
  440. /*-----------------------------------------------------------------*/
  441.  
  442.     void CPPText::InsertTextHandle (Handle theText, long textLen,
  443.                                         long where, 
  444.                                         Boolean ScrollToInsertion)
  445.     /* insert the text pointed to by TheText into the TE area */
  446.     /* in place of/at the current selection */
  447.     {
  448.         Boolean    wasLocked;
  449.         
  450.         if (this->TextBlock && theText)
  451.           {
  452.               wasLocked = (HGetState(theText) & 0x0080) ? TRUE : FALSE;
  453.               HLock(theText);
  454.  
  455.               InsertTextPtr (*theText, textLen, where, ScrollToInsertion);
  456.               
  457.               if (!wasLocked)
  458.                 HUnlock(theText);
  459.           }
  460.         
  461.     }
  462.  
  463. /*-----------------------------------------------------------------*/
  464.  
  465.     void CPPText::SetTextPtr (Ptr theText, long textLen,
  466.                                   Boolean ScrollToInsertion)
  467.     /* set the TE area to contain only the text pointed to by TheText */
  468.     {
  469.         DoSelectAll();        // select all the text in the area
  470.         DoClear();            // delete it all
  471.         InsertTextPtr(theText, Min(textLen, this->maxTextLen), 
  472.                       1, ScrollToInsertion);
  473.     }
  474.  
  475. /*-----------------------------------------------------------------*/
  476.  
  477.     void CPPText::SetTextHandle (Handle theText, long textLen,
  478.                                      Boolean ScrollToInsertion)
  479.     /* set the TE area to contain only the text pointed to by TheText */
  480.     {
  481.         DoSelectAll();        // select all the text in the area
  482.         DoClear();            // delete it all
  483.         InsertTextHandle(theText, Min(textLen, this->maxTextLen), 
  484.                          1, ScrollToInsertion);
  485.     }
  486.  
  487. /*-----------------------------------------------------------------*/
  488.  
  489.     void    CPPText::MakeVisible (Boolean nowVisible)
  490.     /* Hide or show the text edit area, depending on 'nowVisible' */
  491.     {    
  492.         Rect    boundsRect = *GetBounds();
  493.     
  494.         InsetRect (&boundsRect, -1, -1);
  495.         // exit if it is already in the desired state
  496.         if (nowVisible == IsVisible())
  497.           return;
  498.         
  499.         CPPVisualObject::MakeVisible (nowVisible);
  500.  
  501.         // if it is currently invisible, erase it;
  502.         // in either case, invalidate the area to force a redraw
  503.         if (!IsVisible())
  504.           {
  505.             EraseRect (&boundsRect);
  506.             if (this->VScroll)
  507.               HideControl(VScroll);
  508.             if (this->HScroll)
  509.               HideControl(HScroll);
  510.           }
  511.         else
  512.           {
  513.             if (this->VScroll)
  514.               ShowControl(VScroll);
  515.             if (this->HScroll)
  516.               ShowControl(HScroll);
  517.             this->Draw();
  518.           }
  519.           
  520.         InvalRect(&boundsRect);
  521.         
  522.     }
  523.  
  524. /*-----------------------------------------------------------------*/
  525.     
  526.     void CPPText::Draw (void)
  527.     /* draw the text edit area and its controls */
  528.     {
  529.         Rect    tempRect;
  530.         if (this->owningWindow && this->TextBlock && this->IsVisible())
  531.           {
  532.               tempRect = (*this->TextBlock)->viewRect;
  533.               InsetRect (&tempRect, -1, -1);
  534.               FrameRect(&tempRect);
  535.             TEUpdate (&this->owningWindow->portRect, this->TextBlock);
  536.                if (this->VScroll)
  537.                  Draw1Control (this->VScroll);
  538.                if (this->HScroll)
  539.                  Draw1Control (this->HScroll);
  540.           }
  541.     }
  542.     
  543. /*-----------------------------------------------------------------*/
  544.  
  545.     void    CPPText::TargetHilite (Boolean makeTarget)
  546.     /* change the hiliteed state of the object (some objects, like */
  547.     /* lists, have different appearances when they are the target) */
  548.     /* SUBCLASS SHOULD OVERRIDE */
  549.     {
  550.         this->Activate(makeTarget);
  551.         
  552.         CPPVisualObject::TargetHilite(makeTarget);
  553.     }
  554.  
  555. /*-----------------------------------------------------------------*/
  556.  
  557.     Rect    *CPPText::GetBounds (void)
  558.     /* return the boundsrect of the object */
  559.     /* SUBCLASS MUST OVERRIDE */
  560.     {    
  561.         SetRect (&this->bounds, 0, 0, 0, 0);
  562.         
  563.         if (this->isVisible)
  564.           {
  565.             if (this->TextBlock)
  566.               this->bounds = (*this->TextBlock)->viewRect;
  567.             if (this->VScroll)
  568.               UnionRect (&this->bounds, &((*this->VScroll)->contrlRect), &this->bounds);
  569.             if (this->HScroll)
  570.               UnionRect (&this->bounds, &((*this->HScroll)->contrlRect), &this->bounds);
  571.           }
  572.         else
  573.           this->bounds = kEmptyRect;
  574.         
  575.         return &this->bounds;
  576.     }
  577.  
  578.  
  579. /*-----------------------------------------------------------------*/
  580. /*---------------------- PROTECTED METHODS ------------------------*/
  581. /*-----------------------------------------------------------------*/
  582.  
  583.     void    CPPText::MoveContent (short newH, short newV)
  584.     /* move the entire text edit area to the new position */
  585.     {
  586.         Rect        vRect, dRect, bRect = *GetBounds();
  587.         short        deltaH = newH - bRect.left,
  588.                      deltaV = newV - bRect.top;
  589.             
  590.         // move the text block
  591.         if (this->TextBlock)
  592.           {
  593.               vRect = (*this->TextBlock)->viewRect;
  594.               dRect = (*this->TextBlock)->destRect;
  595.             OffsetRect (&((*this->TextBlock)->viewRect), newH-dRect.left, 
  596.                             newV-dRect.top);
  597.             OffsetRect (&((*this->TextBlock)->destRect), newH-dRect.left, 
  598.                             newV-dRect.top);
  599.           }
  600.         // move the vertical scroll bar
  601.         if (this->VScroll)
  602.           {
  603.               vRect = (*this->VScroll)->contrlRect;
  604.               MoveControl (this->VScroll, vRect.left + deltaH, 
  605.                                            vRect.top + deltaV);
  606.           }
  607.         // move the horizontal scroll bar
  608.         if (this->HScroll)
  609.           {
  610.               dRect = (*this->HScroll)->contrlRect;
  611.               MoveControl (this->HScroll, dRect.left + deltaH, 
  612.                                            dRect.top + deltaV);
  613.           }
  614.     }
  615.  
  616. /*-----------------------------------------------------------------*/
  617.  
  618.     void CPPText::ResizeContent (short newWidth, short newHeight)
  619.     {
  620.                     
  621.         TEPtr    TE = (this->TextBlock) ? *this->TextBlock : NULL;
  622.         Rect    VCRect, HCRect, GrowRect, ViewRect, DestRect;
  623.         Rect    PRect;
  624.         
  625.         if (this->owningWindow && this->TextBlock)
  626.           {
  627.               // figure out what the new size of the view area is
  628.               ViewRect = TE->viewRect;
  629.               ViewRect.right = Min (ViewRect.left + newWidth, this->TEmaxWidth)
  630.                                   - ((this->VScroll) ? 15 : 0);
  631.               ViewRect.bottom = Min (ViewRect.top + newHeight, this->TEmaxHeight)
  632.                                   - ((this->HScroll) ? 15 : 0);
  633.               
  634.               // move and resize the controls
  635.               if (this->HScroll)
  636.                 {
  637.                     HideControl (this->HScroll);
  638.                     MoveControl (this->HScroll, ViewRect.left-1, ViewRect.bottom);
  639.                     SizeControl (this->HScroll, (ViewRect.right - ViewRect.left) + 2, 16);
  640.                     ShowControl (this->HScroll);
  641.                 }
  642.  
  643.               if (this->VScroll)
  644.                 {
  645.                     HideControl (this->VScroll);
  646.                     MoveControl (this->VScroll, ViewRect.right, ViewRect.top-1);
  647.                     SizeControl (this->VScroll, 16, (ViewRect.bottom - ViewRect.top) + 2);
  648.                     ShowControl (this->VScroll);
  649.                 }
  650.               
  651.               // resize the text edit area
  652.               TE->viewRect = ViewRect;
  653.               
  654.               // adjust the positions of everything
  655.               AdjustScrollBar();
  656.               CheckInsertion();
  657.           }
  658.     }    
  659.  
  660. /*-----------------------------------------------------------------*/
  661.  
  662.     void CPPText::CheckInsertion (void)
  663.     /* this procedure checks the current insertion point and adjusts */
  664.     /* the text in the window so that the insertion point is always */
  665.     /* visible */
  666.     {
  667.         short    topLine, bottomLine, windowLines;
  668.         TEPtr    TE;
  669.         
  670.         if (this->VScroll && this->TextBlock)
  671.           {
  672.               TE = *this->TextBlock;
  673.               windowLines = LinesInWindow();
  674.               topLine = GetCtlValue (this->VScroll);
  675.               bottomLine = topLine + windowLines;
  676.           
  677.               if (GetCtlMax (this->VScroll) == 0)
  678.                 MoveScrollText();
  679.               else
  680.                 if (TE->selEnd < TE->lineStarts[topLine])
  681.                   ScrollChar (TE->selStart, FALSE);
  682.                 else
  683.                   if (TE->selStart >= TE->lineStarts[bottomLine])
  684.                     ScrollChar (TE->selEnd, TRUE);
  685.           }
  686.     }
  687.  
  688. /*-----------------------------------------------------------------*/
  689.  
  690.       void CPPText::ScrollChar (short charPos, Boolean toBottom)
  691.       /* Adjust the scroll bar to match the current position of the */
  692.       /* text after text has been inserted or deleted */
  693.     {
  694.         short    theLine = 0;
  695.         TEPtr    TE;
  696.         
  697.         if (this->TextBlock && this->VScroll)
  698.           {
  699.               TE = *this->TextBlock;
  700.               while (TE->lineStarts[theLine+1] <= charPos)
  701.                 theLine++;
  702.               if (toBottom)
  703.                 theLine = theLine - (LinesInWindow() - 1);
  704.               SetCtlValue(this->VScroll, theLine);
  705.               MoveScrollText();
  706.           }
  707.     }
  708.     
  709. /*-----------------------------------------------------------------*/
  710. /*----------------------- PRIVATE METHODS -------------------------*/
  711. /*-----------------------------------------------------------------*/
  712.  
  713.     long CPPText::LinesInWindow(void)
  714.     {
  715.         TEPtr    TE = (this->TextBlock) ? *this->TextBlock : NULL;
  716.         
  717.         if (TE)
  718.           return (TE->viewRect.bottom - TE->viewRect.top) / 
  719.                     TE->lineHeight;
  720.         else
  721.           return 0;
  722.     }
  723.  
  724. /*-----------------------------------------------------------------*/
  725.  
  726.     long    CPPText::LinesInText (void)
  727.     {
  728.         long    Lines;
  729.         short    Len;
  730.         TEPtr    TE;
  731.         
  732.         if (this->TextBlock)
  733.           {
  734.               TE = *this->TextBlock;
  735.             Len = TE->teLength;
  736.             
  737.               Lines = TE->nLines;
  738.               if (Len > 0)
  739.                 if (*(*TE->hText + Len-1) == 13)
  740.                   Lines += 1;
  741.               return Lines;
  742.           }
  743.         else
  744.           return 0;
  745.     }
  746.     
  747. /*-----------------------------------------------------------------*/
  748.  
  749.     void CPPText::MoveScrollText ()
  750.     /* Scroll the text to match the settings of the scrollbars */
  751.     {
  752.         long    ScrollValue,
  753.                 height, i, j, 
  754.                 HScrollDiff = 0, VScrollDiff = 0,
  755.                 OldScroll, NewScroll;
  756.         TEPtr    TE;
  757.         
  758.         if (this->TextBlock)
  759.           {
  760.               TE = *this->TextBlock;
  761.             if (this->VScroll)
  762.               {
  763.                   OldScroll = TE->viewRect.top - TE->destRect.top;
  764.                   ScrollValue = GetCtlValue (this->VScroll);
  765.                   NewScroll = ScrollValue * TE->lineHeight;
  766.                   VScrollDiff = OldScroll - NewScroll;
  767.               }          
  768.  
  769.             if (this->HScroll)
  770.               {
  771.                   OldScroll = TE->viewRect.left - TE->destRect.left;
  772.                   ScrollValue = GetCtlValue (this->HScroll);
  773.                   NewScroll = ScrollValue * TE->lineHeight;
  774.                   HScrollDiff = OldScroll - NewScroll;
  775.               }          
  776.  
  777.               if (abs(VScrollDiff) > 32000)
  778.                 {        // if we have reached the limit of textedit, scroll & beep
  779.                     TEScroll (HScrollDiff, SIGN(VScrollDiff) * 32000, this->TextBlock);
  780.                     SysBeep(2);
  781.                 }
  782.             else    // otherwise, do the scrolling, if any is required
  783.               if (VScrollDiff + HScrollDiff != 0)
  784.                   TEScroll (HScrollDiff, VScrollDiff, this->TextBlock);
  785.         }
  786.     }
  787.  
  788. /*-----------------------------------------------------------------*/
  789.  
  790.     pascal void CPPText::Scroll_Up (ControlHandle theControl, short ctlPart)
  791.     /* this method serves as a callback routine for TrackControl; */
  792.     /* It forces the text to scroll up 1 line */
  793.     {
  794.         if (theControl && (GetCtlValue(theControl) - 1 >= GetCtlMin(theControl)))
  795.           {
  796.               SetCtlValue (theControl, GetCtlValue (theControl)-1);
  797.               gCurrentTE->MoveScrollText();
  798.           }    
  799.     }
  800.  
  801. /*-----------------------------------------------------------------*/
  802.  
  803.     pascal void CPPText::Scroll_Down (ControlHandle theControl, 
  804.                                         short ctlPart)
  805.     /* this method serves as a callback routine for TrackControl; */
  806.     /* It forces the text to scroll down 1 line */
  807.     {
  808.         if (theControl && (GetCtlValue(theControl) + 1 <= GetCtlMax(theControl)))
  809.           {
  810.               SetCtlValue (theControl, GetCtlValue (theControl)+1);
  811.               gCurrentTE->MoveScrollText();
  812.           }    
  813.     }
  814.  
  815. /*-----------------------------------------------------------------*/
  816.  
  817.     pascal void CPPText::Scroll_Left (ControlHandle theControl, 
  818.                                         short ctlPart)
  819.     /* this method serves as a callback routine for TrackControl; */
  820.     /* It forces the text to scroll left 1 line */
  821.     {
  822.         if (theControl && (GetCtlValue(theControl) - 1 >= GetCtlMin(theControl)))
  823.           {
  824.               SetCtlValue (theControl, GetCtlValue (theControl)-1);
  825.               gCurrentTE->MoveScrollText();
  826.           }    
  827.     }
  828.  
  829. /*-----------------------------------------------------------------*/
  830.  
  831.     pascal void CPPText::Scroll_Right (ControlHandle theControl, 
  832.                                         short ctlPart)
  833.     /* this method serves as a callback routine for TrackControl; */
  834.     /* It forces the text to scroll right 1 line */
  835.     {
  836.         if (theControl && (GetCtlValue(theControl) + 1 <= GetCtlMax(theControl)))
  837.           {
  838.               SetCtlValue (theControl, GetCtlValue (theControl)+1);
  839.               gCurrentTE->MoveScrollText();
  840.           }    
  841.     }
  842.  
  843. /*-----------------------------------------------------------------*/
  844.  
  845.     pascal Boolean CPPText::AutoScroll (void)
  846.     {
  847.         Boolean    result = TRUE;
  848.         RgnHandle    oldClip = NewRgn();
  849.         Point        mouseLoc;
  850.         Rect        textRect, tempRect;
  851.         
  852.         GetClip (oldClip);
  853.         tempRect = (*gTextBlock)->viewRect;
  854.         if (gVScroll)
  855.           UnionRect (&tempRect, &(*gVScroll)->contrlRect, &tempRect);
  856.         if (gHScroll)
  857.           UnionRect (&tempRect, &(*gHScroll)->contrlRect, &tempRect);
  858.         ClipRect(&tempRect);
  859.         
  860.         GetMouse (&mouseLoc);
  861.         textRect = (*gTextBlock)->viewRect;
  862.         if (mouseLoc.v < textRect.top)
  863.           Scroll_Up (gVScroll, inUpButton);
  864.         else
  865.           if (mouseLoc.v > textRect.bottom)
  866.             Scroll_Down (gVScroll, inDownButton);
  867.  
  868.         if (mouseLoc.h > textRect.right)
  869.           Scroll_Right (gHScroll, inDownButton);
  870.         else
  871.           if (mouseLoc.h < textRect.left)
  872.             Scroll_Left (gHScroll, inUpButton);
  873.           
  874.         SetClip (oldClip);
  875.         DisposeRgn(oldClip);
  876.         return TRUE;
  877.           
  878.     }
  879.  
  880. /*-----------------------------------------------------------------*/
  881.  
  882.     void    CPPText::VPageScroll (long part, long direction)
  883.     /* Scroll the text 1 page either up or down */
  884.     {
  885.         Point    tempPt;
  886.         short    newValue, page;
  887.         TEPtr    TE;
  888.         
  889.         if (this->VScroll && this->TextBlock)
  890.           {
  891.               TE = *this->TextBlock;
  892.               GetMouse (&tempPt);
  893.               while (StillDown())
  894.                 {
  895.                     if (TestControl(this->VScroll, tempPt) == part)
  896.                       {
  897.                           page = direction * ((TE->viewRect.top - 
  898.                                               TE->viewRect.bottom) / 
  899.                                               (TE->lineHeight - 1));
  900.                           newValue = GetCtlValue (this->VScroll) + page;
  901.                           SetCtlValue (this->VScroll, newValue);
  902.                           MoveScrollText();
  903.                       }
  904.                     GetMouse (&tempPt);
  905.                 }    
  906.           }
  907.     }
  908.     
  909. /*-----------------------------------------------------------------*/
  910.  
  911.     void    CPPText::HPageScroll (long part, long direction)
  912.     /* Scroll the text 1 page either left or right */
  913.     {
  914.         Point    tempPt;
  915.         short    newValue, page;
  916.         TEPtr    TE;
  917.         
  918.         if (this->HScroll && this->TextBlock)
  919.           {
  920.               TE = *this->TextBlock;
  921.               GetMouse (&tempPt);
  922.               while (StillDown())
  923.                 {
  924.                     if (TestControl(this->HScroll, tempPt) == part)
  925.                       {
  926.                           page = direction * ((TE->viewRect.right - 
  927.                                               TE->viewRect.left) / 
  928.                                               (TE->lineHeight - 1));
  929.                           newValue = GetCtlValue (this->HScroll) + page;
  930.                           SetCtlValue (this->HScroll, newValue);
  931.                           MoveScrollText();
  932.                       }
  933.                     GetMouse (&tempPt);
  934.                 }    
  935.           }
  936.     }
  937.  
  938. /*-----------------------------------------------------------------*/
  939.  
  940.     void    CPPText::AdjustScrollBar (void)
  941.     /* This procedure turns the scroll bar off if there are fewer */
  942.     /* lines than space for lines, and turns it on to its maximum */
  943.     /* position if there are more */
  944.     {
  945.         short windowLines,
  946.               currentLines,
  947.               currentWidth;
  948.         TEPtr    TE;
  949.         
  950.         if (this->TextBlock)
  951.           {
  952.               TE = *this->TextBlock;
  953.               
  954.             if (this->VScroll)
  955.               {
  956.                   windowLines = LinesInWindow();
  957.                   currentLines = LinesInText();
  958.                   if (currentLines > windowLines)
  959.                     SetCtlMax (this->VScroll, currentLines - windowLines);
  960.                   else
  961.                     {
  962.                         SetCtlMax (this->VScroll, 0);
  963.                         SetCtlMin (this->VScroll, 0);
  964.                     }
  965.               }
  966.             
  967.             if (this->HScroll)
  968.               {
  969.                   currentWidth = abs((TE->viewRect.right - 
  970.                                      TE->destRect.right) / TE->lineHeight);
  971.                   if (currentWidth)
  972.                     SetCtlMax (this->HScroll, currentWidth);
  973.                   else
  974.                     {
  975.                         SetCtlMax (this->HScroll, 0);
  976.                         SetCtlMin (this->HScroll, 0);
  977.                     }
  978.               }
  979.           }
  980.     }
  981.  
  982. /*-----------------------------------------------------------------*/
  983. //
  984. //    Boolean    CPPText::AutoScroll (void)
  985.     /* this is the function which is called if you click in the */
  986.     /* TextEdit field and drag the mouse down or up beyond the */
  987.     /* bottom or top of the window.  It should be set with the */
  988.     /* SetClikLoop function for the TextEdit field you are using */
  989.  /*    {
  990.         RgnHandle    oldClip;
  991.         Point        mouseLoc;
  992.         Rect        textRect;
  993.         Rect        tempRect;
  994.         TEPtr        TE;
  995.         
  996.         if (!this->TextBlock)
  997.           return FALSE;
  998.         TE = *this->TextBlock;
  999.         
  1000.         oldClip = NewRgn();
  1001.         GetClip (oldClip);
  1002.         
  1003.         tempRect = TE->viewRect;
  1004.         if (this->VScroll)
  1005.           UnionRect (&tempRect, &((*this->VScroll)->contrlRect), &tempRect);
  1006.         if (this->HScroll)
  1007.           UnionRect (&tempRect, &((*this->HScroll)->contrlRect), &tempRect);
  1008.         ClipRect (&tempRect);
  1009.         GetMouse(&mouseLoc);
  1010.         textRect= TE->viewRect;
  1011.         if (mouseLoc.v < textRect.top)
  1012.           Scroll_Up(this->VScroll, inUpButton);
  1013.         else
  1014.           if (mouseLoc.v > textRect.bottom)
  1015.             Scroll_Down (this->VScroll, inDownButton);
  1016.     
  1017.         if (mouseLoc.h > textRect.right)
  1018.           Scroll_Right (this->HScroll, inDownButton);
  1019.         else
  1020.           if (mouseLoc.h < textRect.left)
  1021.             Scroll_Left (this->HScroll, inUpButton);
  1022.         
  1023.         SetClip (oldClip);
  1024.         DisposeRgn(oldClip);
  1025.         
  1026.         return TRUE;
  1027.     }
  1028.     */
  1029. /*-----------------------------------------------------------------*/
  1030.  
  1031.     void CPPText::DoVScroller (Point clickPt, short part)
  1032.     /* Handle a click in the vertical scroll bar */
  1033.     {
  1034.         long    Result;
  1035.         
  1036.         gCurrentTE = this;
  1037.         
  1038.         if (this->VScroll)
  1039.           {
  1040.             switch (part) {
  1041.                 case inUpButton     :
  1042.                     Result = TrackControl(this->VScroll, clickPt, 
  1043.                                           (ProcPtr)Scroll_Up);
  1044.                     break;
  1045.                 case inDownButton    :
  1046.                     Result = TrackControl(this->VScroll, clickPt, 
  1047.                                           (ProcPtr)Scroll_Down);
  1048.                     break;
  1049.                 case inPageUp        :
  1050.                     VPageScroll (part, 1);
  1051.                     break;
  1052.                 case inPageDown        :
  1053.                     VPageScroll (part, -1);
  1054.                     break;
  1055.                 case inThumb        :
  1056.                     TrackControl (this->VScroll, clickPt, NULL);
  1057.                     MoveScrollText();
  1058.                     break;
  1059.             }
  1060.           }
  1061.     }
  1062.     
  1063. /*-----------------------------------------------------------------*/
  1064.  
  1065.     void CPPText::DoHScroller (Point clickPt, short part)
  1066.     /* Handle a click in the horizontal scroll bar */
  1067.     {
  1068.         long    Result;
  1069.  
  1070.         gCurrentTE = this;
  1071.         
  1072.         if (this->HScroll)
  1073.           {
  1074.             switch (part) {
  1075.                 case inUpButton     :
  1076.                     Result = TrackControl(this->HScroll, clickPt, 
  1077.                                           (ProcPtr)Scroll_Left);
  1078.                     break;
  1079.                 case inDownButton    :
  1080.                     Result = TrackControl(this->HScroll, clickPt, 
  1081.                                           (ProcPtr)Scroll_Right);
  1082.                     break;
  1083.                 case inPageUp        :
  1084.                     HPageScroll (part, -1);
  1085.                     break;
  1086.                 case inPageDown        :
  1087.                     HPageScroll (part, 1);
  1088.                     break;
  1089.                 case inThumb        :
  1090.                     TrackControl (this->HScroll, clickPt, NULL);
  1091.                     MoveScrollText();
  1092.                     break;
  1093.             }
  1094.           }
  1095.     }
  1096.  
  1097. /*-----------------------------------------------------------------*/
  1098.  
  1099.     void CPPText::MakeTEArea (CPPWindow    *OurWindow,
  1100.                                   Rect *ViewArea,
  1101.                                   Rect *DestArea,
  1102.                                   short    maxLength,
  1103.                                   Boolean UseHScroll,
  1104.                                   Boolean UseVScroll,
  1105.                                   short Font, short FSize)
  1106.     {
  1107.         Rect    DestRect = *DestArea;
  1108.         Rect    ViewRect = *ViewArea;
  1109.         Rect    TempRect;
  1110.         GrafPtr    savePort;
  1111.         short    OldFont, OldFace, OldSize;
  1112.         
  1113.         if (!OurWindow)
  1114.           return;
  1115.         this->owningWindow = OurWindow->GetWindow();
  1116.         this->maxTextLen = maxLength;
  1117.         
  1118.         GetPort(&savePort);
  1119.         SetPort (this->owningWindow);
  1120.     
  1121.         // save the font, size and style of the current grafport
  1122.         OldFont = this->owningWindow->txFont;
  1123.         OldSize = this->owningWindow->txSize;
  1124.         
  1125.         // set the font so that the TE area will appear correctly
  1126.         TextFont (Font);
  1127.         TextSize (FSize);
  1128.     
  1129.         // adjust the size of the view rectangle if there are scrollbars
  1130.         if (UseHScroll)
  1131.           ViewRect.bottom -= (kSBarWidth - 1);
  1132.         if (UseVScroll)
  1133.           ViewRect.right -= (kSBarWidth - 1);
  1134.     
  1135.         this->TextBlock = TENew (&DestRect, &ViewRect);
  1136.         if (!this->TextBlock)
  1137.           {    
  1138.               SetPort (savePort);
  1139.               return;
  1140.           }
  1141.                     
  1142.           if (UseVScroll)
  1143.             {
  1144.                 SetRect (&TempRect, ViewRect.right, ViewRect.top-1,
  1145.                          ViewRect.right+16, ViewRect.bottom+1);
  1146.                 this->VScroll = NewControl(this->owningWindow, &TempRect, "\pVScroller",
  1147.                                            TRUE, 0, 0, 0, scrollBarProc, 1101);
  1148.                 if (!this->VScroll)
  1149.                   {
  1150.                       TEDispose(this->TextBlock);
  1151.                       SetPort (savePort);
  1152.                       return;
  1153.                   }
  1154.             }
  1155.           else
  1156.             this->VScroll = NULL;
  1157.  
  1158.           if (UseHScroll)
  1159.             {
  1160.                 SetRect (&TempRect, ViewRect.left-1, ViewRect.bottom,
  1161.                          ViewRect.right+1, ViewRect.bottom + 16);
  1162.                 this->HScroll = NewControl(this->owningWindow, &TempRect, "\pHScroller",
  1163.                                            TRUE, 0, 0, 0, scrollBarProc, 1102);
  1164.                 if (!this->HScroll)
  1165.                   {
  1166.                       TEDispose(this->TextBlock);
  1167.                       if (this->VScroll)
  1168.                         DisposeControl(this->VScroll);
  1169.                       SetPort (savePort);
  1170.                       return;
  1171.                   }
  1172.             }
  1173.           else
  1174.             this->HScroll = NULL;
  1175.             
  1176.          SetMinSize (70, 70);
  1177.          SetMaxSize ((DestArea->right - DestArea->left) + 16,
  1178.                      (DestArea->bottom - DestArea->top) + 16);
  1179.  
  1180.         SetClikLoop (AutoScroll, this->TextBlock);
  1181.         
  1182.         // restore the original font and size
  1183.         TextSize (OldSize);
  1184.         TextFont (OldFont);
  1185.         
  1186.         // restore the saved port
  1187.         SetPort (savePort);
  1188.     }
  1189.  
  1190. /*-----------------------------------------------------------------*/
  1191.  
  1192.  
  1193.